/********************************************************************************
 * Project Name		[JavaSE_Fundamentals]
 * File Name     	[ToStringUtils.java]
 * Creation Date 	[2015-01-01]
 * 
 * Copyright© ge.y.yang@gmail.com All Rights Reserved
 * 
 * Work hard, play harder, think big and keep fit
 ********************************************************************************/
package reflection;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;

/**
 * 反射 - 编写一个通用的toString方法
 * 
 * @author 不落的太阳(Sean Yang aka ShortPeace)
 * @version 1.0
 * @since jdk 1.8
 * 
 */
public class ToStringUtils {

	/**
	 * 通用的toString方法
	 * 
	 * @param object
	 *            使用此方法的对象
	 * @param builder
	 *            使用的StringBuilder对象
	 * @return object的字符串表示
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 */
	public static String toString(Object object, StringBuilder builder)
			throws IllegalArgumentException, IllegalAccessException {

		if (object == null) {
			return "null";
		}

		Class<?> classType = object.getClass();

		if (classType.isArray()) {// 如果object是数组类型
			String componentName = classType.getComponentType().getSimpleName();
			builder.append(componentName);
			builder.append("[]{");

			int length = Array.getLength(object);
			for (int i = 0; i < length; i++) {
				Object arrayElement = Array.get(object, i);
				if (classType.getComponentType().isPrimitive()) {// 如果数组元素是基本类型
					builder.append(arrayElement);
				} else {// 如果数组元素是引用类型, 则继续递归调用
					builder.append("[");
					toString(arrayElement, builder);
				}
				if (i != (length - 1)) {
					builder.append(", ");
				} else {
					builder.append("}");
				}
			}
		} else {
			String className = classType.getName();
			if (builder.indexOf("[") == -1) {
				builder.append(classType.getSimpleName());
				builder.append("[");
			}
			if (classType == String.class) {// 如果object是String类型
				builder.append((String) object);
			} else if (isSystemClass(className)) { // 如果是系统类
				builder.append(object.toString());
			} else {
				Field[] fields = classType.getDeclaredFields();
				AccessibleObject.setAccessible(fields, true);// 将对象所有属性的访问权限设置为true
				for (int i = 0; i < fields.length; i++) {
					builder.append(fields[i].getName());
					builder.append(" = ");
					builder.append(fields[i].get(object));
					if (i != (fields.length - 1)) {
						builder.append(", ");
					} else {
						builder.append("]");
					}
				}
			}
		}
		return builder.toString();
	}

	/**
	 * 判断是否为系统类, 目前仅判断Java API中的存在的类为系统类<br/>
	 * 
	 * 拓展: 可以将系统类的前缀配置在属性文件中通过IO加载
	 * 
	 * @return true是系统类, false是自定义类
	 */
	private static boolean isSystemClass(String className) {
		boolean flag = false;
		if (className.startsWith("java.") || className.startsWith("javax.") || className.startsWith("org.omg")
				|| className.startsWith("org.w3c") || className.startsWith("org.xml")) {
			flag = true;
		}
		return flag;
	}

	public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
		Employee employee = new Employee(1L, "Sean Yang", new java.util.Date());

		String str = toString(employee, new StringBuilder());
		System.out.println(str);

		int[] intArray = new int[] { 1, 2, 3, 4, 5 };
		str = toString(intArray, new StringBuilder());
		System.out.println(str);

		Employee[] employeeArray = { new Employee(1L, "Sean Yang", new java.util.Date()),
				new Employee(2L, "Sean Yang", new java.util.Date()),
				new Employee(3L, "Sean Yang", new java.util.Date()) };

		// System.out.println(Arrays.toString(employeeArray));
		System.out.println(toString(employeeArray, new StringBuilder()));
	}
}
